package item

import (
	"encoding/json"
	"fmt"
	"time"
	"week13/errors"
	Repo "week13/internal/data/item"
	"week13/internal/job"
)

const (
	ONSALE = 1
	OFFSALE = 0
)
var DefaultRepository Repo.ItemRepository = &Repo.ItemDao{}
type ItemDTO struct {
	ItemId int `json:"itemId"`
	ItemName string `json:"itemName"`
	OnSale int `json:"OnSale"`
	Type int `json:"type"`
	Inventory int `json:"inventory" `
	Addtime int `json:"addtime"`
	Mtime string `json:"mtime"`
}
type Item struct {
	ItemId int
	DTO *ItemDTO
}
//创建商品
func CreateItem(dto ItemDTO) (*Item,error) {
	if dto.ItemName == "" || dto.Type<1{
		return nil, errors.NewIllegalParam("createItem params error")
	}
	dto.ItemId = 0
	do := DTOToDo(dto)
	do.Addtime = int(time.Now().Unix())
	do.OnSale = 0
	do.Inventory = 0
	ret,err := DefaultRepository.Save(do)
	if err != nil {
		return nil, errors.NewExecuteFail(err.Error())
	}
	nItem,err := NewItem(int(ret))
	if err != nil {
		return nil,err
	}
	return nItem,nil
}
//发送产品变动消息到MQ
func sendItemChangeToMQ(dto ItemDTO){
	var sender job.SendJobMessage = job.NewKafkaSender(job.TOPIC_ITEM_CHANGE)
	jsonData,_ := json.Marshal(job.ItemChangeMessage{
		ItemId: dto.ItemId,
		Mtime:  dto.Mtime,
	})
	err := sender.Send(jsonData)
	if err != nil {
		fmt.Println(dto.ItemId," send error:",err.Error())
	}
}
//查找商品缓存数据
func FindItemFromCache(itemId int)  (ItemDTO,error){
	dto := ItemDTO{}
	do, err := DefaultRepository.GetItemFromCache(itemId)
	if err != nil {
		return dto,err

	}
	return DoToDTO(do), nil
}
//设置缓存
func SetItemToCache(dto ItemDTO) error {
	do := DTOToDo(dto)
	return SetItemDoToCache(do)
}

func SetItemDoToCache(do Repo.ItemDo) error {
	err := DefaultRepository.SetItemToCache(do)
	if err != nil {
		return err
	}
	return nil
}
//查找商品数据(优先从缓存中获取)
func FindOneByItemId(itemId int) (ItemDTO,error)  {
	dto, err := FindItemFromCache(itemId)
	if err == nil {
		return dto,nil
	}
	do, err := DefaultRepository.Find(itemId,true)
	if err != nil {
		return ItemDTO{},errors.NewExecuteFail(err.Error())
	}
	dto =DoToDTO(do)
	SetItemToCache(dto)
	return dto,nil
}
//查找一条数据
func FindOne(dto ItemDTO) (ItemDTO,error) {
	filter := DTOToDo(dto)
	do, err := DefaultRepository.FindOneByFilter(filter)
	if err != nil {
		return ItemDTO{},errors.NewExecuteFail(err.Error())
	}
	dto = DoToDTO(do)
	return dto,nil
}
//分页查找
func List(dto ItemDTO,page int,pageSize int) ([]ItemDTO,int64,error) {
	filter := DTOToDo(dto)
	ct, err := DefaultRepository.Count(filter)
	if err !=nil {
		return nil,0,err
	}
	if ct <1 {
		return nil,0,nil
	}
	dos, err := DefaultRepository.List(filter,page,pageSize)
	fmt.Println("dto-----",dos)
	if err != nil {
		return nil,0,err
	}
	dtos := make([]ItemDTO,0)
	jsonData,_ := json.Marshal(dos)
	json.Unmarshal(jsonData,&dtos)
	return dtos,ct,nil
}
//实例化商品
func NewItem(itemId int) (*Item,error) {
	item := &Item{ItemId: itemId}
	dto,err := FindOneByItemId(itemId)
	if err != nil {
		return item,err
	}
	item.DTO = &dto
	return item,nil
}
//获取库存
func (item *Item) Inventory()(int,error){
	data, err := DefaultRepository.Find(item.ItemId,true)
	if err != nil {
		return 0, err
	}
	return data.Inventory,nil
}
//设置商品类型
func (item *Item) SetItemType(itemType int) (int, error) {
	do := Repo.ItemDo{Type: itemType}
	return item.save(do)
}
//设置在售状态
func (item *Item) OnSale() (int, error) {
	do := Repo.ItemDo{OnSale: ONSALE}
	ret, err := item.save(do)
	return ret, err
}
//设置下架状态
func (item *Item) OffSale() (int, error) {
	do := Repo.ItemDo{OnSale: OFFSALE}
	ret, err := item.save(do)
	return ret, err
}
//重置库存
func (item *Item) ResetInventory(num int) (int, error) {
	if num<0 {
		return 0,errors.NewIllegalParam("ResetInventory num <0")
	}
	do := Repo.ItemDo{Inventory: num}
	ret, err := item.save(do)
	if err == nil {
		sendItemChangeToMQ(ItemDTO{ItemId: item.ItemId})
	}
	return ret, err
}
//增加库存
func (item *Item) IncrInventoryOne() (int, error) {
	ret, err := DefaultRepository.IncrInventory(item.ItemId,1)
	if err == nil {
		sendItemChangeToMQ(ItemDTO{ItemId: item.ItemId})
	}
	return ret, err
}
//减少库存
func (item *Item) DecrInventoryOne() (int, error) {
	ret, err := DefaultRepository.DecrInventory(item.ItemId,1)
	if err == nil {
		sendItemChangeToMQ(ItemDTO{ItemId: item.ItemId})
	}
	return ret, err
}
func (item *Item) IncrInventory(num int) (int, error) {
	ret, err := DefaultRepository.IncrInventory(item.ItemId,num)
	if err == nil {
		sendItemChangeToMQ(ItemDTO{ItemId: item.ItemId})
	}
	return ret, err
}
func (item *Item) DecrInventory(num int) (int, error) {
	ret, err := DefaultRepository.DecrInventory(item.ItemId,num)
	if err == nil {
		sendItemChangeToMQ(ItemDTO{ItemId: item.ItemId})
	}
	return ret, err
}
func (item *Item) save(do Repo.ItemDo)(int,error){
	do.ItemId = item.ItemId
	ret,err := DefaultRepository.Save(do)
	if err == nil {
		sendItemChangeToMQ(ItemDTO{ItemId: item.ItemId})
	}
	return ret,err
}
func DTOToDo(dto ItemDTO) Repo.ItemDo{
	jsonData,_ := json.Marshal(dto)
	do := Repo.ItemDo{}
	json.Unmarshal(jsonData,&do)
	return do
}
func DoToDTO(do Repo.ItemDo) ItemDTO {
	jsonData,_ := json.Marshal(do)
	dto := ItemDTO{}
	json.Unmarshal(jsonData,&dto)
	return dto
}
